--
-- CSSE2000 8 Bit Microprocessor
-- Copyright (C) 2011 Nathan Rossi (University of Queensland)
--
-- THIS DESIGN/CODE IS PROVIDED TO YOU UNDER THE FOLLOWING LICENSE:
--
-- All material is restricted to use in the CSSE2000 Project for 2011.
-- You may not redistribute the file/code/design, without the consent of the author.
--
-- DO NOT MODIFY THIS FILE
--

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

package proc_package is
	--
	-- Control Modes in Sub-Processor Elements
	--
	type PROC_ALU_MODE is (NONE,
							ALU_ONESCOMP, ALU_TWOSCOMP,
							ALU_ADD_MODE, ALU_ADD_WC_MODE,
							ALU_SUB_MODE, ALU_SUB_WC_MODE,
							ALU_OR_MODE, ALU_AND_MODE, ALU_XOR_MODE,
							ALU_LOGICAL_LEFT, ALU_LOGICAL_RIGHT,
							ALU_ROTATE_LEFT, ALU_ROTATE_RIGHT,
							ALU_ARTHMETIC_LEFT, ALU_ARTHMETIC_RIGHT);
	attribute ENUM_ENCODING: STRING;
	attribute ENUM_ENCODING of PROC_ALU_MODE:type is 
							"0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111";

	type PROC_PC_MODE is (PC_NORMAL, PC_JUMP_RELATIVE, PC_JUMP_ABSOLUTE);
	type PROC_MUX_SOURCE is (SRC_IMMEDIATE, SRC_ALU_RESULT, SRC_ALU_STATUS, SRC_REGISTER_P_0, SRC_REGISTER_P_1, SRC_SREG_BITSET);
	type PROC_ADDR_MODE is (DIRECT, INDIRECT);

	--
	-- Data Types in Processor
	--
	-- Internal Space Types
	constant PROC_REG_DATA_SIZE : integer := 8;
	subtype PROC_REG_DATA_TYPE is std_logic_vector(PROC_REG_DATA_SIZE-1 downto 0);
	constant PROC_REG_ADDR_SIZE : integer := 4;
	subtype PROC_REG_ADDR_TYPE is std_logic_vector(PROC_REG_ADDR_SIZE-1 downto 0);
	subtype PROC_REG_BIT_INDEX_TYPE is std_logic_vector(2 downto 0);

	-- Program Space Types
	constant PROC_PROG_DATA_SIZE : integer := 16;
	subtype PROC_PROG_DATA_TYPE is std_logic_vector(PROC_PROG_DATA_SIZE-1 downto 0);
	constant PROC_PROG_ADDR_SIZE : integer := 8;
	subtype PROC_PROG_ADDR_TYPE is std_logic_vector(PROC_PROG_ADDR_SIZE-1 downto 0);

	-- Data Space Types
	constant PROC_MEM_DATA_SIZE : integer := 8;
	subtype PROC_MEM_DATA_TYPE is std_logic_vector(PROC_MEM_DATA_SIZE-1 downto 0);
	constant PROC_MEM_ADDR_SIZE : integer := 8;
	subtype PROC_MEM_ADDR_TYPE is std_logic_vector(PROC_MEM_ADDR_SIZE-1 downto 0);

	-- Bus Types
	constant PROC_BUS_DATA_SIZE : integer := 8;
	subtype PROC_BUS_DATA_TYPE is std_logic_vector(PROC_BUS_DATA_SIZE-1 downto 0);
	constant PROC_BUS_ADDR_SIZE : integer := 8;
	subtype PROC_BUS_ADDR_TYPE is std_logic_vector(PROC_BUS_ADDR_SIZE-1 downto 0);

	-- Status Register Types
	constant PROC_SREG_C : integer := 0;
	constant PROC_SREG_H : integer := 1;
	constant PROC_SREG_Z : integer := 2;
	constant PROC_SREG_S : integer := 3;
	constant PROC_SREG_N : integer := 4;
	constant PROC_SREG_V : integer := 5;
	 -- unused range (usage 's(PROC_SREG_UNUSED) <= ...')
	subtype PROC_SREG_UNUSED is natural range 7 downto 6;

	--
	-- Custom Rom Type
	--
	type ROM_FILE_TYPE_GENERIC is array (natural range <>) of PROC_PROG_DATA_TYPE;
	subtype ROM_FILE_TYPE is ROM_FILE_TYPE_GENERIC(0 to (2**PROC_PROG_ADDR_SIZE)-1);
	-- Pad ROM Array Function
	function pad_rom_file (contents : ROM_FILE_TYPE_GENERIC) return ROM_FILE_TYPE;

	function alu_mode_to_bits(mode : PROC_ALU_MODE) return std_logic_vector;
	
end proc_package;

package body proc_package is

	function pad_rom_file (contents : ROM_FILE_TYPE_GENERIC) return ROM_FILE_TYPE is
		variable copy_count : integer;
		variable temp_contents : ROM_FILE_TYPE;
	begin
		copy_count := 0;
		temp_contents := (others => (others => '0'));
		
		for I in contents'range loop
			temp_contents(copy_count) := contents(I);
			copy_count := copy_count + 1;
		end loop;
		
		return temp_contents;
	end pad_rom_file;
    
	function alu_mode_to_bits(mode : PROC_ALU_MODE) return std_logic_vector is 
		variable a : std_logic_vector(3 downto 0);
	begin
		case mode is 
			when ALU_ONESCOMP => a := x"1";
			when ALU_TWOSCOMP => a := x"2";
			when ALU_ADD_MODE => a := x"3";
			when ALU_ADD_WC_MODE => a := x"4";
			when ALU_SUB_MODE => a := x"5";
			when ALU_SUB_WC_MODE => a := x"6";
			when ALU_OR_MODE => a := x"7";
			when ALU_AND_MODE => a := x"8";
			when ALU_XOR_MODE => a := x"9";
			when ALU_LOGICAL_LEFT => a := x"A";
			when ALU_LOGICAL_RIGHT => a := x"B";
			when ALU_ROTATE_LEFT => a := x"C";
			when ALU_ROTATE_RIGHT => a := x"D";
			when ALU_ARTHMETIC_LEFT => a := x"E";
			when ALU_ARTHMETIC_RIGHT => a := x"F";
			when others => a := x"0";
		end case;
		return a;
	end alu_mode_to_bits;
end proc_package;
